package wci.frontend.pascal;

import java.io.IOException;

import wci.frontend.*;
import wci.intermediate.SymTabEntry;
import wci.message.Message;
import wci.message.MessageType;

import static wci.message.MessageType.PARSER_SUMMARY;

/**
 * <h1>PascalParserTD</h1>
 * 
 * <p>
 * Top-Down模式的Pascal Parser
 * </p>
 * 
 * <p>
 * Copyright (c) 2009 by Ronald Mak
 * </p>
 * <p>
 * For instructional purposes only. No warranties.
 * </p>
 */
public class PascalParserTD extends Parser {

	private PascalErrorHandler errorHandler = new PascalErrorHandler();

	public PascalParserTD(Scanner scanner) {
		super(scanner);
	}

	/**
	 * Pascal的解析过程，产生Pascal相关的iCode和symbol table
	 */
	public void parse() throws Exception {
		Token token;
		long startTime = System.currentTimeMillis();

		try {
			while (!((token = nextToken()) instanceof EofToken)) {
				TokenType tokenType = token.getType();
				if (tokenType == PascalTokenType.IDENTIFIER){
					String entry_name = token.getText().toLowerCase();
					//是否出现过
					SymTabEntry entry_existed = symTabStack.lookup(entry_name);
					if (null == entry_existed){
						//第一次出现？
						entry_existed = symTabStack.enterLocal(entry_name);
					}
					entry_existed.appendLineNumber(token.getLineNumber());
				}else if (tokenType==PascalTokenType.ERROR){
					// 留意当token有问题是，它的值表示其错误编码
					errorHandler.flag(token,
							(PascalErrorCode) token.getValue(), this);
				}else{
					//其它暂且忽略
				}
			}
			// 发送编译摘要信息
			float elapsedTime = (System.currentTimeMillis() - startTime) / 1000f;
			sendMessage(new Message(PARSER_SUMMARY, new Number[] {
					token.getLineNumber(), getErrorCount(), elapsedTime }));
		} catch (IOException e) {
			errorHandler.abortTranslation(PascalErrorCode.IO_ERROR, this);
		}
	}

	public int getErrorCount() {
		return errorHandler.getErrorCount();
	}
}
